package com.ncmmall.mall.controller.business.marketing.coupon;

import com.ncmmall.application.business.coupon.CouponApplication;
import com.feijin.commons.exceptions.IllegalRequestException;
import com.feijin.commons.lang.Requires;
import com.feijin.commons.webs.Webs;
import com.ncmmall.domain.business.goods.Goods;
import com.ncmmall.domain.business.goods.QGoods;
import com.ncmmall.domain.business.goods.channel.GoodsChannel;
import com.ncmmall.domain.business.goods.channel.QGoodsChannel;
import com.ncmmall.domain.business.marketing.coupon.Coupon;
import com.ncmmall.domain.business.marketing.coupon.CouponChannel;
import com.ncmmall.domain.business.marketing.coupon.CouponGoods;
import com.ncmmall.domain.business.marketing.coupon.CouponMemberDraw;
import com.ncmmall.domain.business.marketing.coupon.QCoupon;
import com.ncmmall.domain.business.marketing.coupon.QCouponChannel;
import com.ncmmall.domain.business.marketing.coupon.QCouponGoods;
import com.ncmmall.domain.business.merchant.MerchantGoodsChannel;
import com.ncmmall.domain.business.merchant.QMerchantGoodsChannel;
import com.ncmmall.mall.controller.securitys.shiro.Securitys;
import com.ncmmall.mall.params.PageParams;
import com.ncmmall.querychannel.QueryPage;
import com.ncmmall.querychannel.QueryPageRequest;
import com.ncmmall.querychannel.service.QueryChannelService;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 优惠券管理
 *
 * @author linxs
 * @date 2019-07-10 17:44
 */
@Controller
@RequestMapping(value = "/merchant/coupon")
@Slf4j
public class MerchantCouponController {

    @Autowired
    private QueryChannelService queryChannelService;

    @Autowired
    private CouponApplication couponApplication;

    /**
     * 优惠券列表
     */
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    private String list(Model model, PageParams pageParams, Coupon coupon) {
        QueryPageRequest pageRequest = new QueryPageRequest().setPageNo(pageParams.getPageNo());
        Map<String, Object> params = Maps.newHashMap();
        params.put("id", Securitys.currentUser().getId());
        String hql = builderSQL("select u from Coupon u where u.merchant.id = :id ", params, coupon);
        QueryPage<Coupon> page = queryChannelService.findPage(hql, pageRequest.setParams(params), Coupon.class);

        model.addAttribute("page", page).addAttribute("params", coupon);

        return "merchant/marketing/coupon/list";
    }


    /**
     * 适用的商品列表
     */
    @RequestMapping(value = "/chooseGoodses", method = RequestMethod.GET)
    private String chooseGoodses(Model model, PageParams pageParams, Goods coupon, String channels) {
        QueryPageRequest pageRequest = new QueryPageRequest().setPageNo(pageParams.getPageNo());
        Map<String, Object> params = Maps.newHashMap();
        params.put("id", Securitys.currentUser().getId());
        String hql = builderGoodsSQL("select u from Goods u where u.merchant.id = :id and u.status = 3 ", params, coupon, channels);
        QueryPage<Goods> page = queryChannelService.findPage(hql, pageRequest.setParams(params), Goods.class);

        model.addAttribute("page", page)
                .addAttribute("params", coupon)
                .addAttribute("channels", queryChannelService.findAll("select c from GoodsChannel c where c.deleteStatus = 0 and  c.level = 1 and c.status = 1 ", GoodsChannel.class));

        return "merchant/marketing/coupon/chooseGoodses";
    }


    /**
     * 选择赠品优惠券的赠品商品
     */
    @RequestMapping(value = "/chooseComplimentaryGoods", method = RequestMethod.GET)
    private String chooseComplimentaryGoods(Model model, PageParams pageParams, Goods params) {

        Map<String, Object> map = new HashMap<>();
        map.put("id", Securitys.currentUser().getId());

        String hql = builderGoodsSkuHQL(map, params);
        QueryPageRequest pageRequest = new QueryPageRequest().setPageNo(pageParams.getPageNo());
        QueryPage<Goods> page = queryChannelService.findPage(hql, pageRequest.setParams(map), Goods.class);

        model.addAttribute("page", page)
                .addAttribute("params", params)
                .addAttribute("channels", queryChannelService.findAll("select c from GoodsChannel c where c.deleteStatus = 0 and  c.level = 1 and c.status = 1 ", GoodsChannel.class));

        return "merchant/marketing/coupon/chooseComplimentaryGoods";
    }

    private String builderGoodsSkuHQL(Map<String, Object> params, Goods goods) {
        String sql = "select g from Goods g where g.merchant.id = :id and g.status = 3 and g.isSupplier = 0";
        if (goods.getGoodsChannel() != null && goods.getGoodsChannel().getId() > 0) {
            sql += " and g.goodsChannel.id = :cid ";
            params.put("cid", goods.getGoodsChannel().getId());
        } else if (goods.getGoodsChannel() != null && goods.getGoodsChannel().getParent() != null && goods.getGoodsChannel().getParent().getId() > 0) {
            sql += " and g.goodsChannel.parent.id = :cid ";
            params.put("cid", goods.getGoodsChannel().getParent().getId());
        } else if (goods.getGoodsChannel() != null && goods.getGoodsChannel().getParent() != null && goods.getGoodsChannel().getParent().getParent().getId() > 0) {
            sql += " and g.goodsChannel.parent.parent.id = :cid ";
            params.put("cid", goods.getGoodsChannel().getParent().getParent().getId());
        }
        if (!Strings.isNullOrEmpty(goods.getName())) {
            sql += " and g.name like :name ";
            params.put("name", "%" + goods.getName() + "%");
        }
        return sql + " order by g.createTime desc";
    }

    /**
     * 获取选择的适用商品列表
     */
    @RequestMapping(value = "/queryGoodses", method = RequestMethod.GET)
    @ResponseBody
    private Map<String, Object> queryGoodses(@RequestParam("ids") String ids) {

        if (StringUtils.isBlank(ids)) {
            return ImmutableMap.of("status", true, "goodses", Collections.emptyList());
        }

        List<Long> goodsIds = Splitter.on("-").omitEmptyStrings().trimResults().splitToList(ids).stream().map(Long::valueOf).collect(Collectors.toList());
        List<Goods> goodses = queryChannelService.findAll(QGoods.goods.id.in(goodsIds), Goods.class);
        return ImmutableMap.of("status", true, "goodses", goodses);

    }

    /**
     * @param channels 商品分类id，多个以_分割
     */
    private String builderGoodsSQL(String sql, Map<String, Object> params, Goods goods, String channels) {

        if (StringUtils.isNotBlank(channels)) {
            List<Long> channelIds = Arrays.stream(StringUtils.split(channels, "_")).map(Long::valueOf).collect(Collectors.toList());
            sql += " and u.goodsChannel.parent.parent.id in (:ids)";
            params.put("ids", channelIds);
        }

        if (goods.getIsSupplier() > 0) {
            sql += " and u.isSupplier = 1 ";
        } else {
            sql += " and u.isSupplier = 0 ";
        }

        if (null != goods.getGoodsChannel() && goods.getGoodsChannel().getId() > 0) {
            goods.setGoodsChannel(queryChannelService.findOne(QGoodsChannel.goodsChannel.id.eq(goods.getGoodsChannel().getId()), GoodsChannel.class));

            sql += " and u.goodsChannel.id = :cid ";
            params.put("cid", goods.getGoodsChannel().getId());

        } else if (null != goods.getGoodsChannel() && goods.getGoodsChannel().getParent().getId() > 0) {
            goods.getGoodsChannel().setParent(queryChannelService.findOne(QGoodsChannel.goodsChannel.id.eq(goods.getGoodsChannel().getParent().getId()), GoodsChannel.class));

            sql += " and u.goodsChannel.parent.id = :cid ";
            params.put("cid", goods.getGoodsChannel().getParent().getId());

        } else if (null != goods.getGoodsChannel() && goods.getGoodsChannel().getParent().getParent().getId() > 0) {
            goods.getGoodsChannel().getParent().setParent(queryChannelService.findOne(QGoodsChannel.goodsChannel.id.eq(goods.getGoodsChannel().getParent().getParent().getId()), GoodsChannel.class));

            sql += " and u.goodsChannel.parent.parent.id = :cid ";
            params.put("cid", goods.getGoodsChannel().getParent().getParent().getId());
        }

        if (goods.getMerchant() != null && goods.getMerchant().getId() > 0) {
            sql += " and u.merchant.id = :merchantId ";
            params.put("merchantId", goods.getMerchant().getId());
        }

        if (goods.getStatus() > 0) {
            sql += " and u.status = :status ";
            params.put("status", goods.getStatus());
        } else {
            sql += " and u.status in (3,6) ";
        }

        if (!Strings.isNullOrEmpty(goods.getGoodsNo())) {
            sql += " and u.goodsNo like :goodsno ";
            params.put("goodsno", "%" + goods.getGoodsNo() + "%");
        }

        if (!Strings.isNullOrEmpty(goods.getName())) {
            sql += " and u.name like :name ";
            params.put("name", "%" + goods.getName() + "%");
        }


        if (!Strings.isNullOrEmpty(goods.getOrderByCreateTime())) {
            sql += " order by u.createTime " + goods.getOrderByCreateTime();
        } else if (!Strings.isNullOrEmpty(goods.getOrderByPrice())) {
            sql += " order by u.defaultPrice " + goods.getOrderByPrice();
        } else if (!Strings.isNullOrEmpty(goods.getOrderByStore())) {
            sql += " order by u.store " + goods.getOrderByStore();
        } else if (!Strings.isNullOrEmpty(goods.getOrderBySalesVolume())) {
            sql += " order by u.salesVolume " + goods.getOrderBySalesVolume();
        } else {
            sql += " order by u.createTime desc ";
        }

        return sql;
    }


    /**
     * 查看详情
     */
    @RequestMapping(value = "/{id}/detail", method = RequestMethod.GET)
    private String detail(Model model, @PathVariable("id") long id) {
        List<GoodsChannel> channels = queryChannelService.findAll(QMerchantGoodsChannel.merchantGoodsChannel.merchant.id.eq(Securitys.currentUser().getId()), MerchantGoodsChannel.class).stream().map(MerchantGoodsChannel::getChannel).collect(Collectors.toList());
        List<String> channelNames = queryChannelService.findAll(QCouponChannel.couponChannel.coupon.id.eq(id), CouponChannel.class).stream().map(input -> input.getChannel().getName()).collect(Collectors.toList());
        List<CouponGoods> goodses = queryChannelService.findAll(QCouponGoods.couponGoods.coupon.id.eq(id), CouponGoods.class);
        model.addAttribute("_method", "PUT").addAttribute("coupon", queryChannelService.findOne(QCoupon.coupon.id.eq(id), Coupon.class)).addAttribute("channels", channels).addAttribute("goodses", goodses).addAttribute("channelNames", channelNames);
        return "merchant/marketing/coupon/detail";
    }


    /**
     * 编辑优惠券信息
     */
    @RequestMapping(value = "/{id}/modify", method = RequestMethod.GET)
    private String modify(Model model, @PathVariable("id") long id) {
        List<GoodsChannel> channels = queryChannelService.findAll("select m.channel from MerchantGoodsChannel m where m.merchant.id = :mid and m.channel.deleteStatus = 0", ImmutableMap.of("mid", Securitys.currentUser().getId()), GoodsChannel.class);
        List<String> channelNames = queryChannelService.findAll(QCouponChannel.couponChannel.coupon.id.eq(id), CouponChannel.class).stream().map(input -> input.getChannel().getName()).collect(Collectors.toList());
        List<CouponGoods> goodses = queryChannelService.findAll(QCouponGoods.couponGoods.coupon.id.eq(id), CouponGoods.class);
        model.addAttribute("_method", "PUT")
                .addAttribute("coupon", queryChannelService.findOne(QCoupon.coupon.id.eq(id), Coupon.class))
                .addAttribute("channels", channels)
                .addAttribute("goodses", goodses)
                .addAttribute("channelNames", channelNames);
        return "merchant/marketing/coupon/form";
    }


    /**
     * 编辑优惠券信息
     */
    @RequestMapping(value = "/{id}/modify", method = RequestMethod.PUT)
    @ResponseBody
    private Map<String, Object> modify(@RequestHeader("X-Requested-With") String requestWith, Coupon coupon) {
        try {
            if (!Webs.isAjaxRequest(requestWith)) {
                throw new IllegalRequestException("request must be Ajax!");
            }
            Requires.isTrue(coupon.getValidityType() == 1 || coupon.getValidityType() == 2, "请选择有效期类型");
            if (coupon.getValidityType() == 2) {
                Requires.isTrue(coupon.getValidityDay() > 0, "可使用天数不正确");
            } else {
                Requires.hasLength(coupon.getValidityBeginDay(), "有效期开始时间不能为空");
                Requires.hasLength(coupon.getValidityEndDay(), "有效期结束时间不能为空");
            }
            couponApplication.modify(coupon);
            return ImmutableMap.of("status", true);
        } catch (Exception e) {
            log.error("[编辑优惠券信息异常]", e);
            return ImmutableMap.of("status", false);
        }
    }

    /**
     * 申请上架
     */
    @RequestMapping(value = "/applyPutaway", method = RequestMethod.PUT)
    @ResponseBody
    private Map<String, Object> applyPutaway(@RequestHeader("X-Requested-With") String requestWith, @RequestParam("id") long id) {
        try {
            if (!Webs.isAjaxRequest(requestWith)) {
                throw new IllegalRequestException("request must be Ajax!");
            }
            Coupon coupon = queryChannelService.findOne(QCoupon.coupon.id.eq(id), Coupon.class);
            couponApplication.putaway(coupon);
            return ImmutableMap.of("status", true);
        } catch (Exception e) {
            log.error("[编辑优惠券信息异常]", e);
            return ImmutableMap.of("status", false);
        }
    }

    /**
     * 提交审核优惠券
     */
    @RequestMapping(value = "/applyProcess", method = RequestMethod.PUT)
    @ResponseBody
    private Map<String, Object> applyProcess(@RequestHeader("X-Requested-With") String requestWith, @RequestParam("id") long id) {
        try {
            if (!Webs.isAjaxRequest(requestWith)) {
                throw new IllegalRequestException("request must be Ajax!");
            }
            Coupon coupon = queryChannelService.findOne(QCoupon.coupon.id.eq(id), Coupon.class);
            couponApplication.applyProcess(coupon);
            return ImmutableMap.of("status", true);
        } catch (Exception e) {
            log.error("[编辑优惠券信息异常]", e);
            return ImmutableMap.of("status", false);
        }
    }

    /**
     * 批量申请上架
     */
    @RequestMapping(value = "/applysPutaway", method = RequestMethod.PUT)
    @ResponseBody
    private Map<String, Object> applysPutaway(@RequestHeader("X-Requested-With") String requestWith, @RequestParam("ids") String data) {
        try {
            if (!Webs.isAjaxRequest(requestWith)) {
                throw new IllegalRequestException("request must be Ajax!");
            }
            List<String> ids = Splitter.on(";").omitEmptyStrings().trimResults().splitToList(data);
            couponApplication.putaways(ids.stream().map(input -> queryChannelService.findOne(QCoupon.coupon.id.eq(Long.parseLong(input)), Coupon.class)).collect(Collectors.toList()));
            return ImmutableMap.of("status", true);
        } catch (Exception e) {
            log.error("[批量申请上架优惠券异常]", e);
            return ImmutableMap.of("status", false);

        }
    }


    /**
     * 批量下架优惠券
     */
    @RequestMapping(value = "/soldoutss", method = RequestMethod.PUT)
    @ResponseBody
    private Map<String, Object> soldoutss(@RequestHeader("X-Requested-With") String requestWith, @RequestParam("ids") String data) {
        try {
            if (!Webs.isAjaxRequest(requestWith)) {
                throw new IllegalRequestException("request must be Ajax!");
            }
            List<String> ids = Splitter.on(";").omitEmptyStrings().trimResults().splitToList(data);
            couponApplication.soldoutss(ids.stream().map(input -> queryChannelService.findOne(QCoupon.coupon.id.eq(Long.parseLong(input)), Coupon.class)).collect(Collectors.toList()));
            return ImmutableMap.of("status", true);
        } catch (Exception e) {
            log.error("[批量下架优惠券异常]", e);
            return ImmutableMap.of("status", false);
        }
    }

    /**
     * 下架优惠券
     */
    @RequestMapping(value = "/soldout", method = RequestMethod.PUT)
    @ResponseBody
    private Map<String, Object> soldout(@RequestHeader("X-Requested-With") String requestWith, @RequestParam("id") long id) {
        try {
            if (!Webs.isAjaxRequest(requestWith)) {
                throw new IllegalRequestException("request must be Ajax!");
            }
            Coupon coupon = queryChannelService.findOne(QCoupon.coupon.id.eq(id), Coupon.class);
            couponApplication.soldout(coupon);
            return ImmutableMap.of("status", true);
        } catch (Exception e) {
            log.error("[下架优惠券异常]", e);
            return ImmutableMap.of("status", false);
        }
    }

    /**
     * 添加优惠券页面
     */
    @RequestMapping(value = "/create", method = RequestMethod.GET)
    private String create(Model model) {
        Coupon coupon = new Coupon();
        List<GoodsChannel> channels = queryChannelService.findAll("select m.channel from MerchantGoodsChannel m where m.merchant.id = :mid and m.channel.deleteStatus = 0 and m.channel.status = 1", ImmutableMap.of("mid", Securitys.currentUser().getId()), GoodsChannel.class);
        model.addAttribute("_method", "POST").addAttribute("coupon", coupon).addAttribute("channels", channels);
        return "merchant/marketing/coupon/form";
    }

    /**
     * 添加优惠券
     */
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    @ResponseBody
    private Map<String, Object> create(@RequestHeader("X-Requested-With") String requestWith, Coupon coupon) {
        try {
            if (!Webs.isAjaxRequest(requestWith)) {
                throw new IllegalRequestException("request must be Ajax!");
            }
            Requires.isTrue(coupon.getValidityType() == 1 || coupon.getValidityType() == 2, "请选择有效期类型");
            if (coupon.getValidityType() == 2) {
                Requires.isTrue(coupon.getValidityDay() > 0, "可使用天数不正确");
            } else {
                Requires.hasLength(coupon.getValidityBeginDay(), "有效期开始时间不能为空");
                Requires.hasLength(coupon.getValidityEndDay(), "有效期结束时间不能为空");
            }
            coupon.setMerchant(Securitys.currentUser());
            couponApplication.create(coupon);
            return ImmutableMap.of("status", true, "message", "添加成功");
        } catch (IllegalArgumentException e) {
            return ImmutableMap.of("status", false, "message", e.getMessage());
        } catch (Exception e) {
            log.error("[添加优惠券信息异常]", e);
            return ImmutableMap.of("status", false, "message", "添加异常");
        }
    }

    /**
     * 删除优惠券
     */
    @RequestMapping(value = "/remove", method = RequestMethod.DELETE)
    @ResponseBody
    private Map<String, Object> remove(@RequestHeader("X-Requested-With") String requestWith, @RequestParam("id") long id) {
        try {
            if (!Webs.isAjaxRequest(requestWith)) {
                throw new IllegalRequestException("request must be Ajax!");
            }
            Coupon coupon = queryChannelService.findOne(QCoupon.coupon.id.eq(id), Coupon.class);
            couponApplication.remove(coupon);
            return ImmutableMap.of("status", true);
        } catch (Exception e) {
            log.error("[权限删除异常]", e);
            return ImmutableMap.of("status", false);
        }
    }


    /**
     * 条件筛选
     */
    private String builderSQL(String sql, Map<String, Object> params, Coupon coupon) {

        if (coupon.getStatus() > 0) {
            sql += " and u.status = :status ";
            params.put("status", coupon.getStatus());
        }

        if (!Strings.isNullOrEmpty(coupon.getName())) {
            sql += " and u.name like :name ";
            params.put("name", "%" + coupon.getName() + "%");
        }

        if (coupon.getType() > 0) {
            sql += " and u.type = :type ";
            params.put("type", coupon.getType());
        }

        return sql + " order by u.createTime desc";
    }

    /**
     * 优惠券领取列表
     */
    @RequestMapping(value = "/{id}/recordList", method = RequestMethod.GET)
    public String recordList(Model model, PageParams pageParams, CouponMemberDraw params, @PathVariable long id) {
        QueryPageRequest pageRequest = new QueryPageRequest().setPageNo(pageParams.getPageNo()).setPageSize(pageParams.getPageSize());
        Map<String, Object> map = Maps.newHashMap();
        map.put("cid", id);
        String hql = builderHQL("select c from CouponMemberDraw c where c.coupon.id = :cid ", map, params);
        QueryPage<CouponMemberDraw> page = queryChannelService.findPage(hql, pageRequest.setParams(map), CouponMemberDraw.class);

        model.addAttribute("page", page).addAttribute("params", params);

        return "merchant/marketing/coupon/record";
    }

    private String builderHQL(String sql, Map<String, Object> map, CouponMemberDraw params) {
        if (null != params.getMember() && StringUtils.isNotBlank(params.getMember().getMobile())) {
            sql += " and c.member.mobile = :mobile";
            map.put("mobile", params.getMember().getMobile());
        }

        if (params.getStatus() > 0) {
            sql += " and c.status = :status";
            map.put("status", params.getStatus());
        }

        sql += " order by c.drawTime desc";
        return sql;
    }

}
